home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Various / DevDisk 65 (1989)(DevWare PD).zip / DevDisk 65 (1989)(DevWare PD).adf / 3d / 3d.doc < prev    next >
Text File  |  1990-08-07  |  27KB  |  1,132 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.                                      3D Library
  28.  
  29.                                      version 1.0
  30.  
  31.  
  32.  
  33.                                   by Steven Ludtke
  34.  
  35.  
  36.  
  37.                                    January 5, 1990
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.                                       NOTICE
  74.  
  75.  
  76.  
  77.           The 3d library and all associated software in this distribution
  78.  
  79.           is Copyright 1990 by Steven J. Ludtke. You have permission to
  80.  
  81.           use and/or modify this code for any purpose commercial or non-
  82.  
  83.           commercial with two conditions : I must be given credit in any
  84.  
  85.           distributed product's documentation, and if any part of this
  86.  
  87.           package is used in any commercial product (even Shareware) one
  88.  
  89.           free copy of said software must be sent to me at the following
  90.  
  91.           address : Steven Ludtke, 406 Yale Cir., Glenwood Springs, CO
  92.  
  93.           81601; all other royalties are waived. This Copyright notice
  94.  
  95.           must accompany any distributions of any part of this package,
  96.  
  97.           and in general, the package should be distributed intact, with
  98.  
  99.           no modifications. This notice must not be removed from the 3d.c,
  100.  
  101.           test.c, and cube.c source code in this release.
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.                               Page 2 - January 5, 1990
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.                                     Introduction
  140.  
  141.                                 ---------------------
  142.  
  143.                        
  144.  
  145.             This library represents an attempt to provide the Amiga
  146.  
  147.           community with a high speed, easy to use 3d display library for
  148.  
  149.           C programmers. The library uses the transformation matrix
  150.  
  151.           method, which is the fastest method I know to do 3d
  152.  
  153.           transformations while still providing relatively intuitive
  154.  
  155.           rotations. Integer arithmetic is used for speed. Additionally,
  156.  
  157.           the data is stored in a format that will make it easy to
  158.  
  159.           optimize the code in assembly language. I wrote the code for
  160.  
  161.           Aztec C, but I haven't converted anything to assembly language
  162.  
  163.           yet, so the current version should work with Lattice as well. I
  164.  
  165.           haven't tested it, but I don't believe I did anything that is
  166.  
  167.           compiler dependent. 
  168.  
  169.             The library provides what I consider relatively high speed 3d
  170.  
  171.           displays. It can rotate and draw roughly 500 lines/second. Once
  172.  
  173.           I've converted the rotation code to optimized assembly, I expect
  174.  
  175.           the time required for the calculation portion of the display to
  176.  
  177.           be reduced by at least a factor of 4. With the Amiga's graphics
  178.  
  179.           coprocessor, filled polygons can be drawn almost (perhaps 70-
  180.  
  181.           80%) as fast as the lines.
  182.  
  183.             Since a number of the parameters used in the library are
  184.  
  185.           application specific, the 'library' is actually a C source file
  186.  
  187.           that you include in your program. This is done primarily for
  188.  
  189.           speed. If some of the parameters were variables rather than
  190.  
  191.           #defines, the library would run significantly slower. The code
  192.  
  193.           is relatively small, and it seems unlikely that more than one 3d
  194.                               Page 3 - January 5, 1990
  195.           application would be active at one time, so C source seems to me
  196.  
  197.           to be a reasonable way to go. If anyone has a better idea for
  198.  
  199.           future versions, I'd love to hear it.
  200.  
  201.  
  202.  
  203.             Included in this package are the following :
  204.  
  205.           3d.c     - The actual library code. This file is included in any
  206.  
  207.                      program you use the 3d routines in. It must appear in
  208.  
  209.                      the correct place in your program. Read the instr. or
  210.  
  211.                      look at one of the sample programs for more info. 
  212.  
  213.           3d.doc   - This file.
  214.  
  215.           makefile - An Aztec makefile for the two sample programs.
  216.  
  217.           cube.c   - A sample program that does double buffered animation
  218.  
  219.                      of a cube moving around. There is a reason it doesn't
  220.  
  221.                      move very smoothly. Look at the code before you think
  222.  
  223.                      that's the best the library can do.
  224.  
  225.           test.c   - A sample program that allows you to display 3d files
  226.  
  227.                      that are in a standard (non-IFF) format. Several
  228.  
  229.                      sample files are included. Look at the source for
  230.  
  231.                      instructions.
  232.  
  233.           cube.3d  - A cube for use with test.c
  234.  
  235.           earth.3d - Outline of the earth's continents for use with 
  236.  
  237.  
  238.  
  239.  
  240.  
  241.                      test.c. It should work pretty well with d3surf().
  242.  
  243.           rocket.3d- This is an example of a file that won't work
  244.  
  245.                      correctly with 3dsurf(). 
  246.  
  247.           lay.3d   - 4 squares to try with test.c
  248.  
  249.  
  250.  
  251.             The two sample programs were written for Aztec C ver 3.6. As
  252.  
  253.           far as I know it will work as is with Lattice, but I could be
  254.  
  255.           wrong. I didn't supply executable for the samples to save a
  256.  
  257.           little space in the distribution.
  258.  
  259.             I have tested all the routines fairly well myself, but this
  260.  
  261.           release is the first time anyone else has had the chance to use
  262.  
  263.           any of this stuff. I should probably call this version a beta-
  264.  
  265.           test release, but I won't. If you have any problems or
  266.  
  267.           suggestions I strongly encourage you to send me a message.
  268.  
  269.           Besides, knowing that someone actually is using this package
  270.  
  271.           would give my ego a little boost.
  272.  
  273.  
  274.  
  275.           I can be contacted via any of the following :
  276.  
  277.           stevel@tybalt.caltech.edu  (until June 90)
  278.  
  279.           stevel@citiago.bitnet      (until June 90)
  280.  
  281.           gluon@theta.caltech.edu
  282.  
  283.           72335,1537  (compuserve)
  284.  
  285.           Steve Ludtke, 1-54 Caltech, Pasadena CA 91126   (until June 90)
  286.  
  287.           Steve Ludtke, 406 Yale Cir, Glen. Spgs. CO 81601 (after that)
  288.  
  289.  
  290.  
  291.             My current plans for the next version are as follows :
  292.  
  293.           1. Convert much of the code to assembly for speed.
  294.  
  295.           2. Perhaps add alternative methods for specifying angles, etc...
  296.                               Page 4 - January 5, 1990
  297.           I've heard of some scheme using quaternation (sp?) that's
  298.  
  299.           supposed to be easier for many applications.
  300.  
  301.           3. Perhaps I'll try to add some primitive shading routines
  302.  
  303.           (simple lighting effects).
  304.  
  305.           4. Anything you suggest ...
  306.  
  307.  
  308.  
  309.             Please talk to me. I like to get mail. Btw, this code should
  310.  
  311.           be pretty easy to convert for use on other machines. All you
  312.  
  313.           really need to change is the actual graphics function calls.
  314.  
  315.  
  316.  
  317.  
  318.  
  319.             Here's the actual programming info. Info on structures follows
  320.  
  321.           the function information. I tried to make it as easy to use as
  322.  
  323.           possible.
  324.  
  325.  
  326.  
  327.             Before your try to write your own code, you should probably
  328.  
  329.           look at one of the examples. I'll summarize the basic steps
  330.  
  331.           here.
  332.  
  333.             Before you include the 3d.c file, you need to have several
  334.  
  335.           #define statements in you program. If necessary you can replace
  336.  
  337.           some of the defines with global variables, but you should avoid
  338.  
  339.           this as it will slow the program down. The defines you need are
  340.  
  341.           as follows :
  342.  
  343.  
  344.  
  345.           #define D3VDIST  5000   <- This is the distance from the
  346.  
  347.                                      observer to the vanishing point. It
  348.  
  349.                                      is only used with rotatev().
  350.  
  351.           #define REZ 1024        <- Since the program uses integer
  352.  
  353.                                      math, it must use several bits
  354.  
  355.                                      for fractional calculations. 1024
  356.  
  357.                                      would give 3 digits of accuracy. This
  358.  
  359.                                      number needs to be a power of 2 for
  360.  
  361.                                      upward compatibility. In general it
  362.  
  363.                                      should be at least as large as the
  364.  
  365.                                      # of pixels in the display you use.
  366.  
  367.                                      The larger it is, the smaller your
  368.  
  369.                                      space for points is. REZ=1024 leaves
  370.  
  371.                                      you with ~4,000,000 possible values
  372.  
  373.                                      for 'x','y','z'.
  374.                               Page 5 - January 5, 1990
  375.           #define REZB 10         <- This is the number of bits in REZ. It
  376.  
  377.                                      isn't currently used. It will be in
  378.  
  379.                                      the next version, so update it.
  380.  
  381.           #define XCEN 250        <- This is the x coord (in the bitmap)
  382.  
  383.                                      of the center (x=0) coordinate for 3d
  384.  
  385.                                      displays.
  386.  
  387.           #define YCEN 100        <- Same for y coord.
  388.  
  389.           #define XHI  600        <- This is the highest x value in your
  390.  
  391.                                      bitmap. Anything above this will be
  392.  
  393.                                      clipped by the drawing routines.
  394.  
  395.           #define YHI  180        <- Same for y.
  396.  
  397.           #define XLO  0          <- Low x clipping value.
  398.  
  399.           #define YLO  0          <- Low y clipping value.
  400.  
  401.           #define ASPECT  22/10   <- This is the aspect ratio used to
  402.  
  403.                                      insurea square coord system on the
  404.  
  405.                                      screen. 22/10 is correct for 640X200 
  406.  
  407.                                      mode. Obviously 11/10 should be used
  408.  
  409.                                      in 320X200 mode.
  410.  
  411.           #include "3d.c"
  412.  
  413.  
  414.  
  415.  
  416.  
  417.             Next, you should initialize a VECTOR structure with enough
  418.  
  419.           free memory for your vertex data. Don't forget to allocate
  420.  
  421.           memory for 'tx','ty', and 'tz', too. Allocate memory for a LINES
  422.  
  423.           array as well. Now you can fill in the data in the VECTOR and
  424.  
  425.           LINES structures. Information on this data appears near the end
  426.  
  427.           of the documentation. 
  428.  
  429.             Now set up a window or screen (something with a valid
  430.  
  431.           RastPort) or two for double buffering. If you intend to use
  432.  
  433.           d3surf(), call Init3Ras() with one or both RastPorts.
  434.  
  435.             Now SetDrMd() for all RastPorts. If you don't have color data
  436.  
  437.           in your LINES structure, also do a SetAPen() and a SetOPen()
  438.  
  439.           (for surfaces) for all RastPorts.
  440.  
  441.             Now you can actually display data. setxfm() allows you to set
  442.  
  443.           the viewpoint for the drawing. rotatev() or rotate() is used to
  444.  
  445.           actually perform the rotations with or without perspective.
  446.  
  447.           d3surf() and d3lines() can then be used to render the data in a
  448.  
  449.           RastPort. 
  450.  
  451.             When you're all done, don't forget to call Exit3d() if you
  452.  
  453.           called Init3Ras(). DON'T call it if you only used d3lines().
  454.  
  455.           Simple huh ??? : )
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.                               Page 6 - January 5, 1990
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.           FUNCTION DEFINITIONS :
  486.  
  487.  
  488.  
  489.           setxfm - Set rotation and translation values for next xform.
  490.  
  491.  
  492.  
  493.           USAGE :
  494.  
  495.           setxfm(a1,a1,a3,x,y,z,m,d)
  496.  
  497.           double a1,a2,a3;
  498.  
  499.           long x,y,z,m,d;
  500.  
  501.  
  502.  
  503.           FUNCTION :
  504.  
  505.               This routine sets transformation matrix values based on the
  506.  
  507.           parameters you pass it. The actual matrix is a global array,
  508.  
  509.           however for upward compatibility's sake, you shouldn't access it
  510.  
  511.           except through this routine.
  512.  
  513.  
  514.  
  515.           INPUTS :
  516.  
  517.               The three parameters, 'a1-a3' are rotation angles in radians
  518.  
  519.           (see the description of rotations following the structure
  520.  
  521.           definitions). 'x','y','z' are translation parameters. Since
  522.  
  523.           positional values are integral, the translation values must also
  524.  
  525.           be integral.
  526.  
  527.              'n' and 'd' are scaling factors. Since integer arithmetic is
  528.  
  529.           used, a fraction is used for the scaling factor. 'n' is the
  530.  
  531.           numerator and 'd' is the denominator of the scaling factor. The
  532.  
  533.           way this is implemented, it doesn't slow the translations down,
  534.  
  535.           so if you don't need it just set 'n' and 'd' to 1. It will be
  536.  
  537.           just like they didn't exist.
  538.                               Page 7 - January 5, 1990
  539.  
  540.  
  541.           OUTPUTS :
  542.  
  543.           None.
  544.  
  545.           ---------------------------------------
  546.  
  547.  
  548.  
  549.           rotate - Rotates an array of vectors using the current setxfm()
  550.  
  551.           vals without perspective.
  552.  
  553.  
  554.  
  555.           USAGE :
  556.  
  557.           rotate(v,n)
  558.  
  559.           VECTOR *v;
  560.  
  561.           int n;
  562.  
  563.  
  564.  
  565.           FUNCTION:
  566.  
  567.           This routine actually performs the translation of a group of
  568.  
  569.           points in 3-space based on the parameters set by setxfm().
  570.  
  571.  
  572.  
  573.           INPUTS :
  574.  
  575.           'v' points to a vector structure which must be initialized with
  576.  
  577.           pointers to all 6 arrays of size >='n'. The first 'n' vectors
  578.  
  579.           will be rotated. Note that the 'x','y','z' VECTOR values are
  580.  
  581.  
  582.  
  583.  
  584.  
  585.           unchanged. These values are transformed, and the results are
  586.  
  587.           stored in 'tx','ty','tz'. If you wish to transform a subset of
  588.  
  589.           the points, a separate VECTOR structure pointing to the
  590.  
  591.           beginning of the subset can be used.
  592.  
  593.  
  594.  
  595.           OUTPUTS:
  596.  
  597.           none.
  598.  
  599.           ---------------------------------------
  600.  
  601.  
  602.  
  603.           rotatev - Rotates an array of vectors using the current setxfm
  604.  
  605.           vals with perspective.
  606.  
  607.  
  608.  
  609.           USAGE :
  610.  
  611.           rotatev(v,n)
  612.  
  613.           VECTOR *v;
  614.  
  615.           int n;
  616.  
  617.  
  618.  
  619.           FUNCTION:
  620.  
  621.           This routine actually performs the translation of a group of
  622.  
  623.           points in 3-space based on the parameters set by setxfm(). The
  624.  
  625.           only difference between this routine and rotate() is the
  626.  
  627.           addition of perspective.
  628.  
  629.  
  630.  
  631.           INPUTS :
  632.  
  633.           'v' points to a vector structure which must be initialized with
  634.  
  635.           pointers to all 6 arrays of size >='n'. The first 'n' vectors
  636.  
  637.           will be rotated. Note that the 'x','y','z' VECTOR values are
  638.  
  639.           unchanged. These values are transformed, and the results are
  640.                               Page 8 - January 5, 1990
  641.           stored in 'tx','ty','tz'. If you wish to transform a subset of
  642.  
  643.           the points, a separate VECTOR structure pointing to the
  644.  
  645.           beginning of the subset can be used.
  646.  
  647.  
  648.  
  649.           OUTPUTS:
  650.  
  651.           none.
  652.  
  653.           ---------------------------------------
  654.  
  655.  
  656.  
  657.           Init3Ras - Sets a rastport up for area fills.
  658.  
  659.  
  660.  
  661.           USAGE:
  662.  
  663.           Init3Ras(rp,rp2)
  664.  
  665.           struct RastPort *rp,*rp2;
  666.  
  667.  
  668.  
  669.           FUNCTION:
  670.  
  671.           This routine should be called once for each RastPort to be used
  672.  
  673.           with d3surf(). If it is called more than once with the same
  674.  
  675.           RastPort it could cause serious problems. This routine only
  676.  
  677.           needs to be called if d3surf() is going to be used. If only
  678.  
  679.           d3lines() is going to be used, you can save some memory by not
  680.  
  681.           calling this routine.
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.           INPUTS:
  690.  
  691.           'rp' and 'rp2' point to RastPorts which will be used with
  692.  
  693.           d3surf(). d3surf uses area fill operations, so the RastPort it
  694.  
  695.           uses must be given temporary storage for use in the filling.
  696.  
  697.           'rp2' should be set to NULL if only one RastPort is to be used.
  698.  
  699.           If both are passed, they will be assigned the same temporary
  700.  
  701.           storage area, thus saving a significant amount of memory.
  702.  
  703.  
  704.  
  705.           OUTPUTS:
  706.  
  707.           None.
  708.  
  709.           ---------------------------------------
  710.  
  711.  
  712.  
  713.           Exit3d - Frees up the memory allocated by Init3Ras.
  714.  
  715.  
  716.  
  717.           USAGE :
  718.  
  719.           Exit3d(rp)
  720.  
  721.           struct RastPort *rp;
  722.  
  723.  
  724.  
  725.           FUNCTION:
  726.  
  727.           This routine frees up the memory allocated by Init3Ras().
  728.  
  729.  
  730.  
  731.           INPUTS:
  732.  
  733.           'rp' points to a RastPort initialized with Init3Ras(). If 2
  734.  
  735.           RastPorts were initialized with a SINGLE call to Init3Ras(),
  736.  
  737.           only ONE of the two should be passed to Exit3d(), and neither
  738.  
  739.           should be used with area fills again.
  740.  
  741.             I should explain this in more detail. If two RastPorts are
  742.                               Page 9 - January 5, 1990
  743.           initialized with a single Init3Ras() call, both RastPorts will
  744.  
  745.           point to the same scratch memory area. Exit3d() frees this
  746.  
  747.           memory up. After you call it for one of the two RastPorts, the
  748.  
  749.           other one will point to an unallocated area in memory. If a fill
  750.  
  751.           operation is done at this time, it can cause all sorts of nasty
  752.  
  753.           problems. Be warned.
  754.  
  755.  
  756.  
  757.           OUTPUTS:
  758.  
  759.           None.
  760.  
  761.           ---------------------------------------
  762.  
  763.  
  764.  
  765.  
  766.  
  767.           d3lines - Draw a group of lines connecting points in 3 space.
  768.  
  769.  
  770.  
  771.           USAGE:
  772.  
  773.           d3lines(vector,line,n,rp)
  774.  
  775.           VECTOR *vector;
  776.  
  777.           LINES *line;
  778.  
  779.           int n;
  780.  
  781.           struct RastPort *rp;
  782.  
  783.  
  784.  
  785.           FUNCTION:
  786.  
  787.           This routine actually draws lines connecting one or more points
  788.  
  789.           in 3-space. See the information on the VECTOR and LINES
  790.  
  791.           structures for more info.
  792.  
  793.  
  794.  
  795.           INPUTS:
  796.  
  797.           'vector' points to a VECTOR structure with information on the
  798.  
  799.           points to be used in the line drawing. 'line' points to an array
  800.  
  801.           of LINES structures which contains a description of how the
  802.  
  803.           lines are to be drawn. 'n' is the number of elements in the
  804.  
  805.           array pointed to by 'line'. 'rp' points to the RastPort where
  806.  
  807.           the lines should be drawn.
  808.  
  809.  
  810.  
  811.           OUTPUTS:
  812.  
  813.           none.
  814.  
  815.           ---------------------------------------
  816.  
  817.  
  818.  
  819.           d3surf - Draw a group of surfaces in 3 space.
  820.  
  821.  
  822.                               Page 10 - January 5, 1990
  823.           USAGE:
  824.  
  825.           d3lines(vector,line,n,rp)
  826.  
  827.           VECTOR *vector;
  828.  
  829.           LINES *line;
  830.  
  831.           int n;
  832.  
  833.           struct RastPort *rp;
  834.  
  835.  
  836.  
  837.           FUNCTION:
  838.  
  839.           This routine is just like d3lines(), except filled polygons are
  840.  
  841.           drawn rather than lines. The polygons are sorted before drawing,
  842.  
  843.           so hidden line removal is accomplished.
  844.  
  845.  
  846.  
  847.           INPUTS:
  848.  
  849.           'vector' points to a VECTOR structure with information on the
  850.  
  851.           points to be used in the surface drawing. 'line' points to an
  852.  
  853.           array of LINES structures which contains a description of how
  854.  
  855.           the surfaces are to be drawn. 'n' is the number of elements in
  856.  
  857.           the array pointed to by line. 'rp' points to the RastPort where
  858.  
  859.           the surfaces should be drawn.
  860.  
  861.  
  862.  
  863.           OUTPUTS:  none.
  864.  
  865.  
  866.  
  867.  
  868.  
  869.           STRUCTURES :
  870.  
  871.  
  872.  
  873.           VECTOR ->
  874.  
  875.           long *x,*y,*z;
  876.  
  877.           long *tx,*ty,*tz;
  878.  
  879.  
  880.  
  881.             This structure points to the data for all the vertices that
  882.  
  883.           are transformed. 'x','y','z' are arrays with the untransformed
  884.  
  885.           vertex information. 'tx','ty','tz' are arrays which contain the
  886.  
  887.           transformed equivalents of the vertices. 'tx','ty','tz' are
  888.  
  889.           filled in by rotate() and rotatev(). They must be initialized to
  890.  
  891.           point to sufficiently large areas of free memory by the user.
  892.  
  893.             The 'x','y','z' values represent vertical pixels on the
  894.  
  895.           screen. ie - the point (10,1,10) without perspective would
  896.  
  897.           appear 10 pixels below and 22 pixels to the right of the defined
  898.  
  899.           center (using a 22/10) aspect ratio.
  900.  
  901.           -----------------------------------------
  902.  
  903.  
  904.  
  905.           LINES ->
  906.  
  907.           unsigned short l;
  908.  
  909.           unsigned short nl : 1,nc : 1, nco : 1;
  910.  
  911.  
  912.  
  913.             For those of you not familiar with the above notation, nl, nc,
  914.  
  915.           and nco are 1 bit integers allocated within a single unsigned
  916.  
  917.           short. An array of LINES structures contains the information for
  918.  
  919.           line/polygon drawing. The fact that 'l' is allocated as a short
  920.  
  921.           means that you can't have more than 2^16 vertices in any single
  922.  
  923.           array. Hopefully this won't present any problems.
  924.                               Page 11 - January 5, 1990
  925.           The array of LINES should be used as follows :
  926.  
  927.           'l' contains a vertex number in a VECTOR structure or a color
  928.  
  929.           (see below).
  930.  
  931.  
  932.  
  933.           'nl' is set if this vertex is the beginning of a new
  934.  
  935.           line/polygon.
  936.  
  937.  
  938.  
  939.           'nc' is set if 'l' represents a new fill color for polygons.
  940.  
  941.  
  942.  
  943.           'nco' is set if 'l' represents a new outline color for polygons,
  944.  
  945.           or a new line color for line drawing.
  946.  
  947.  
  948.  
  949.             If filled shapes are to be drawn, not just lines, be sure that
  950.  
  951.           each new line represents a new polygon. That is, don't draw two
  952.  
  953.           filled shapes with one continuous line. This would look fine for
  954.  
  955.           d3lines(), but would produce strange effects with d3surf().
  956.  
  957.           Points in filled shapes need not be in the same plane, but think
  958.  
  959.           carefully before trying this. Some shapes may look strange in
  960.  
  961.           some perspectives. 
  962.  
  963.             Color changes with d3lines() may occur anywhere. However,
  964.  
  965.           color changes used with d3surf() must occur only immediately
  966.  
  967.  
  968.  
  969.  
  970.  
  971.           after a nl=1 element. This is due to the way hidden line removal
  972.  
  973.           works. Every nl=1 element is taken to be the beginning of a new
  974.  
  975.           polygon. These polygons are then sorted so the farthest ones are
  976.  
  977.           drawn first. Color changes occurring before a nl=1 point will be
  978.  
  979.           attached to the wrong polygon when they are sorted. Color
  980.  
  981.           changes in the middle of the shape may not have the desired
  982.  
  983.           effect (after 1 or more lines have been added).
  984.  
  985.  
  986.  
  987.           Here is a sample LINES array to make this all more clear :
  988.  
  989.  
  990.  
  991.               l   nl   nc   nco
  992.  
  993.           0   0    1    0    0          <- Starts a shape, vertex 0
  994.  
  995.           1   2    0    0    1          <- Changes to outline color 2
  996.  
  997.           2   1    0    1    0          <- Changes to filled color 1
  998.  
  999.           3   1    0    0    0        
  1000.  
  1001.           4   2    0    0    0
  1002.  
  1003.           5   3    0    0    0 
  1004.  
  1005.           6   0    0    0    0          <- Closes the quad., not necessary
  1006.  
  1007.                                            for d3surf().
  1008.  
  1009.           7   3    0    0    1          <- Changes outline color. This is
  1010.  
  1011.                                            fine for d3lines(), but won't
  1012.  
  1013.                                            change correctly for d3surf().
  1014.  
  1015.           8   4    1    0    0          <- New shape
  1016.  
  1017.           9   5    0    0    0
  1018.  
  1019.           10  6    0    0    0          <- No color was defined after the
  1020.  
  1021.                                            new shape started, so the color
  1022.  
  1023.                                            from the last drawn shape will
  1024.  
  1025.                                            be used. The shape is not
  1026.                               Page 12 - January 5, 1990
  1027.                                            closed. d3surf() will close the
  1028.  
  1029.                                            shape anyway. d3lines won't.
  1030.  
  1031.            
  1032.  
  1033.             In the above example, 0-6 will draw a quadrilateral in color 2
  1034.  
  1035.           if d3lines() is used. It will draw a filled quad., filled with
  1036.  
  1037.           color 1 and outlined in color 2, if d3surf() is used.
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.           ROTATIONS, AND HOW THEY'RE DONE
  1044.  
  1045.           -------------------------------
  1046.  
  1047.             This program uses a very standard scheme for rotating objects
  1048.  
  1049.           which is completely general. That is, you can observe your
  1050.  
  1051.           'scene' from absolutely any imaginable perspective (within the
  1052.  
  1053.           bounds of integer math). 
  1054.  
  1055.             The axes are set up as follows :
  1056.  
  1057.  
  1058.  
  1059.                Z|   / Y
  1060.  
  1061.                 |  /
  1062.  
  1063.                 | /
  1064.  
  1065.                 |/
  1066.  
  1067.                 -------------  
  1068.  
  1069.                             X
  1070.  
  1071.  
  1072.  
  1073.            That is, the X axis is the screen x axis, the Z axis is the
  1074.  
  1075.           screen y axis, and the Y axis goes positive into the screen.
  1076.  
  1077.  
  1078.  
  1079.             Rotations are defined in terms of three steps. 'a1' defines a
  1080.  
  1081.           rotation angle from the X axis in the X-Y plane. 'a2' then
  1082.  
  1083.           rotates the specified number of radians away from the Z axis in
  1084.  
  1085.           the Y-Z plane. Finally 'a3' defines a rotation in radians from
  1086.  
  1087.           the new (rotated) X axis in the new X-Y plane. 
  1088.  
  1089.             Explained another way : Say the ground is in the X-Y plane, ie
  1090.  
  1091.           going into the screen. 'a1' would spin an object resting on the
  1092.  
  1093.           ground as if it were a top. 'a2' would cause this rotated object
  1094.  
  1095.           to tilt on the screen, just like the Aster*ids spaceship spins.
  1096.  
  1097.           'a3' would take the tilted object and spin it along the tilted
  1098.                               Page 13 - January 5, 1990
  1099.           plane. a3 is a bit hard to picture, play with it.
  1100.  
  1101.             I know this is somewhat complex, but you can do any possible
  1102.  
  1103.           rotation with it once you get the hang of it. It may also be
  1104.  
  1105.           easier to visualize if you picture the observer moving, rather
  1106.  
  1107.           than the object being rotated. I may try to add a few other
  1108.  
  1109.           schemes in the next version. We'll see what I can find.
  1110.  
  1111.             For those of you who are interested you can see how this
  1112.  
  1113.           transformation works in "Classical Mechanics" by Goldstein on
  1114.  
  1115.           page 146. (What can I say, I'm a physics major.)
  1116.  
  1117.  
  1118.  
  1119.           ---------
  1120.  
  1121.  
  1122.  
  1123.             Again, if you run into any bugs or problems please let me
  1124.  
  1125.           know. Also keep in mind that, while you may feel free to modify
  1126.  
  1127.           this code, you might have compatibility problems if you do. I
  1128.  
  1129.           tried to comment the code as well as possible for those of you
  1130.  
  1131.           who feel like making changes. Have fun !!!
  1132.